home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / EMULATOR / GBDK_BIN / examples / c / sound < prev    next >
Text File  |  1997-01-08  |  23KB  |  874 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. #define ARROW_CHAR 3
  5. #define SPACE_CHAR ' '
  6.  
  7. #define ARROW_X    0
  8. #define VAL_X      15
  9. #define TITLE_Y    0
  10. #define FIRST_X    (ARROW_X+1)
  11. #define FIRST_Y    (TITLE_Y+2)
  12.  
  13. #define PLAY       0x20
  14. #define FREQUENCY  0x21
  15.  
  16. #define MIN(x,y) ((x) > (y) ? (y) : (x))
  17. #define MAX(x,y) ((x) < (y) ? (y) : (x))
  18.  
  19. #define NB_MODES   5
  20.  
  21. extern unsigned char _reg_0x10;
  22. extern unsigned char _reg_0x11;
  23. extern unsigned char _reg_0x12;
  24. extern unsigned char _reg_0x13;
  25. extern unsigned char _reg_0x14;
  26. extern unsigned char _reg_0x15;
  27. extern unsigned char _reg_0x16;
  28. extern unsigned char _reg_0x17;
  29. extern unsigned char _reg_0x18;
  30. extern unsigned char _reg_0x19;
  31. extern unsigned char _reg_0x1A;
  32. extern unsigned char _reg_0x1B;
  33. extern unsigned char _reg_0x1C;
  34. extern unsigned char _reg_0x1D;
  35. extern unsigned char _reg_0x1E;
  36. extern unsigned char _reg_0x1F;
  37. extern unsigned char _reg_0x20;
  38. extern unsigned char _reg_0x21;
  39. extern unsigned char _reg_0x22;
  40. extern unsigned char _reg_0x23;
  41. extern unsigned char _reg_0x24;
  42. extern unsigned char _reg_0x25;
  43. extern unsigned char _reg_0x26;
  44.  
  45. enum notes {
  46.   C0, Cd0, D0, Dd0, E0, F0, Fd0, G0, Gd0, A0, Ad0, B0,
  47.   C1, Cd1, D1, Dd1, E1, F1, Fd1, G1, Gd1, A1, Ad1, B1,
  48.   C2, Cd2, D2, Dd2, E2, F2, Fd2, G2, Gd2, A2, Ad2, B2,
  49.   C3, Cd3, D3, Dd3, E3, F3, Fd3, G3, Gd3, A3, Ad3, B3,
  50.   C4, Cd4, D4, Dd4, E4, F4, Fd4, G4, Gd4, A4, Ad4, B4,
  51.   C5, Cd5, D5, Dd5, E5, F5, Fd5, G5, Gd5, A5, Ad5, B5,
  52.   SILENCE, END
  53. };
  54.  
  55. unsigned int frequencies[] = {
  56.   44, 156, 262, 363, 457, 547, 631, 710, 786, 854, 923, 986,
  57.   1046, 1102, 1155, 1205, 1253, 1297, 1339, 1379, 1417, 1452, 1486, 1517,
  58.   1546, 1575, 1602, 1627, 1650, 1673, 1694, 1714, 1732, 1750, 1767, 1783,
  59.   1798, 1812, 1825, 1837, 1849, 1860, 1871, 1881, 1890, 1899, 1907, 1915,
  60.   1923, 1930, 1936, 1943, 1949, 1954, 1959, 1964, 1969, 1974, 1978, 1982,
  61.   1985, 1988, 1992, 1995, 1998, 2001, 2004, 2006, 2009, 2011, 2013, 2015
  62. };
  63.  
  64. unsigned char music[] = {
  65.   C3, C3, G3, G3, A3, A3, G3, SILENCE,
  66.   F3, F3, E3, E3, D3, D3, C3, SILENCE,
  67.   G3, G3, F3, F3, E3, E3, D3, D3,
  68.   G3, G3, F3, F3, E3, E3, D3, D3,
  69.   C3, C3, G3, G3, A3, A3, G3, SILENCE,
  70.   F3, F3, E3, E3, D3, D3, C3, SILENCE,
  71.   END
  72. };
  73.  
  74. struct Params {
  75.   char *name;
  76.   unsigned int max;
  77. };
  78.  
  79. struct Params params_0[] = {
  80.   { "Main Controls" , 0    },
  81.   { "All On/Off"    , 1    },
  82.   { "Vin->SO1"      , 1    },
  83.   { "Vin->SO2"      , 1    },
  84.   { "SO1 Volume"    , 7    },
  85.   { "SO2 Volume"    , 7    },
  86.   { NULL            , 0    }
  87. };
  88.  
  89. struct Params params_1[] = {
  90.   { "Sound Mode #1" , 0    },
  91.   { "Swp Time"      , 7    },
  92.   { "Swp Mode"      , 1    },
  93.   { "Swp Shifts"    , 7    },
  94.   { "Pat Duty"      , 3    },
  95.   { "Sound Len"     , 63   },
  96.   { "Env Init"      , 15   },
  97.   { "Env Mode"      , 1    },
  98.   { "Env Nb Swp"    , 7    },
  99.   { "Frequency"     , 2047 },
  100.   { "Cons Sel"      , 1    },
  101.   { "Out to SO1"    , 1    },
  102.   { "Out to SO2"    , 1    },
  103.   { "On/Off"        , 1    },
  104.   { NULL            , 0    }
  105. };
  106.  
  107. struct Params params_2[] = {
  108.   { "Sound Mode #2" , 0    },
  109.   { "Pat Duty"      , 3    },
  110.   { "Sound Len"     , 63   },
  111.   { "Env Init"      , 15   },
  112.   { "Env Mode"      , 1    },
  113.   { "Env Nb Step"   , 7    },
  114.   { "Frequency"     , 2047 },
  115.   { "Cons Sel"      , 1    },
  116.   { "Out to SO1"    , 1    },
  117.   { "Out to SO2"    , 1    },
  118.   { "On/Off"        , 1    },
  119.   { NULL            , 0    }
  120. };
  121.  
  122. struct Params params_3[] = {
  123.   { "Sound Mode #3" , 0    },
  124.   { "Sound On/Off"  , 1    },
  125.   { "Sound Len"     , 255  },
  126.   { "Sel Out Level" , 3    },
  127.   { "Frequency"     , 2047 },
  128.   { "Cons Sel"      , 1    },
  129.   { "Out to SO1"    , 1    },
  130.   { "Out to SO2"    , 1    },
  131.   { "On/Off"        , 1    },
  132.   { NULL            , 0    }
  133. };
  134.  
  135. struct Params params_4[] = {
  136.   { "Sound Mode #4" , 0    },
  137.   { "Sound Len"     , 63   },
  138.   { "Env Init"      , 15   },
  139.   { "Env Mode"      , 1    },
  140.   { "Env Nb Step"   , 7    },
  141.   { "Poly Cnt Freq" , 15   },
  142.   { "Poly Cnt Step" , 1    },
  143.   { "Poly Cnt Div"  , 7    },
  144.   { "Cons Sel"      , 1    },
  145.   { "Out to SO1"    , 1    },
  146.   { "Out to SO2"    , 1    },
  147.   { "On/Off"        , 1    },
  148.   { NULL            , 0    }
  149. };
  150.  
  151. struct Params *params_array[] = {
  152.   params_0,
  153.   params_1,
  154.   params_2,
  155.   params_3,
  156.   params_4,
  157. };
  158.  
  159. struct Params *params;
  160.  
  161. struct SoundReg {
  162.   struct {
  163.     /* 0xFF10 */
  164.     unsigned int sweepShifts     : 3;
  165.     unsigned int sweepMode       : 1;
  166.     unsigned int sweepTime       : 3;
  167.     unsigned int unused_1        : 1;
  168.  
  169.     /* 0xFF11 */
  170.     unsigned int soundLength     : 6;
  171.     unsigned int patternDuty     : 2;
  172.  
  173.     /* 0xFF12 */
  174.     unsigned int envNbSweep      : 3;
  175.     unsigned int envMode         : 1;
  176.     unsigned int envInitialValue : 4;
  177.  
  178.     /* 0xFF13 */
  179.     unsigned int frequencyLow    : 8;
  180.  
  181.     /* 0xFF14 */
  182.     unsigned int frequencyHigh   : 3;
  183.     unsigned int unused_2        : 3;
  184.     unsigned int counter_ConsSel : 1;
  185.     unsigned int restart         : 1;
  186.   } mode1;
  187.   struct {
  188.     /* 0xFF15 */
  189.     unsigned int unused_1        : 8;
  190.  
  191.     /* 0xFF16 */
  192.     unsigned int soundLength     : 6;
  193.     unsigned int patternDuty     : 2;
  194.  
  195.     /* 0xFF17 */
  196.     unsigned int envNbStep       : 3;
  197.     unsigned int envMode         : 1;
  198.     unsigned int envInitialValue : 4;
  199.  
  200.     /* 0xFF18 */
  201.     unsigned int frequencyLow    : 8;
  202.  
  203.     /* 0xFF19 */
  204.     unsigned int frequencyHigh   : 3;
  205.     unsigned int unused_2        : 3;
  206.     unsigned int counter_ConsSel : 1;
  207.     unsigned int restart         : 1;
  208.   } mode2;
  209.   struct {
  210.     /* 0xFF1A */
  211.     unsigned int unused_1        : 7;
  212.     unsigned int on_Off          : 1;
  213.  
  214.     /* 0xFF1B */
  215.     unsigned int soundLength     : 8;
  216.  
  217.     /* 0xFF1C */
  218.     unsigned int unused_2        : 5;
  219.     unsigned int selOutputLevel  : 2;
  220.     unsigned int unused_3        : 1;
  221.  
  222.     /* 0xFF1D */
  223.     unsigned int frequencyLow    : 8;
  224.  
  225.     /* 0xFF1E */
  226.     unsigned int frequencyHigh   : 3;
  227.     unsigned int unused_4        : 3;
  228.     unsigned int counter_ConsSel : 1;
  229.     unsigned int restart         : 1;
  230.   } mode3;
  231.   struct {
  232.     /* 0xFF1F */
  233.     unsigned int unused_1        : 8;
  234.  
  235.     /* 0xFF20 */
  236.     unsigned int soundLength     : 6;
  237.     unsigned int unused_2        : 2;
  238.  
  239.     /* 0xFF21 */
  240.     unsigned int envNbStep       : 3;
  241.     unsigned int envMode         : 1;
  242.     unsigned int envInitialValue : 4;
  243.  
  244.     /* 0xFF22 */
  245.     unsigned int polyCounterDiv   : 3;
  246.     unsigned int polyCounterStep  : 1;
  247.     unsigned int polyCounterFreq  : 4;
  248.  
  249.     /* 0xFF23 */
  250.     unsigned int unused_3        : 6;
  251.     unsigned int counter_ConsSel : 1;
  252.     unsigned int restart         : 1;
  253.   } mode4;
  254.   struct {
  255.     /* 0xFF24 */
  256.     unsigned int SO1_OutputLevel : 3;
  257.     unsigned int Vin_SO1         : 1;
  258.     unsigned int SO2_OutputLevel : 3;
  259.     unsigned int Vin_SO2         : 1;
  260.  
  261.     /* 0xFF25 */
  262.     unsigned int Sound1_To_SO1   : 1;
  263.     unsigned int Sound2_To_SO1   : 1;
  264.     unsigned int Sound3_To_SO1   : 1;
  265.     unsigned int Sound4_To_SO1   : 1;
  266.     unsigned int Sound1_To_SO2   : 1;
  267.     unsigned int Sound2_To_SO2   : 1;
  268.     unsigned int Sound3_To_SO2   : 1;
  269.     unsigned int Sound4_To_SO2   : 1;
  270.  
  271.     /* 0xFF26 */
  272.     unsigned int Sound1_On_Off   : 1;
  273.     unsigned int Sound2_On_Off   : 1;
  274.     unsigned int Sound3_On_Off   : 1;
  275.     unsigned int Sound4_On_Off   : 1;
  276.     unsigned int unused_1        : 3;
  277.     unsigned int global_On_Off   : 1;
  278.   } control;
  279. };
  280.  
  281. struct SoundReg *soundReg;
  282.  
  283. int current_value(int mode, int line)
  284. {
  285.   if(mode == 0) {
  286.     switch(line)
  287.       {
  288.       case 0: /* global_On_Off */
  289.     return soundReg->control.global_On_Off;
  290.       case 1: /* Vin_SO1 */
  291.     return soundReg->control.Vin_SO1;
  292.       case 2: /* Vin_SO2 */
  293.     return soundReg->control.Vin_SO2;
  294.       case 3: /* SO1_OutputLevel */
  295.     return soundReg->control.SO1_OutputLevel;
  296.       case 4: /* SO2_OutputLevel */
  297.     return soundReg->control.SO2_OutputLevel;
  298.       }
  299.   } else if(mode == 1) {
  300.     switch(line)
  301.       {
  302.       case 0: /* sweepTime */
  303.     return soundReg->mode1.sweepTime;
  304.       case 1: /* sweepMode */
  305.     return soundReg->mode1.sweepMode;
  306.       case 2: /* sweepShifts */
  307.     return soundReg->mode1.sweepShifts;
  308.       case 3: /* patternDuty */
  309.     return soundReg->mode1.patternDuty;
  310.       case 4: /* soundLength */
  311.     return soundReg->mode1.soundLength;
  312.       case 5: /* envInitialValue */
  313.     return soundReg->mode1.envInitialValue;
  314.       case 6: /* envMode */
  315.     return soundReg->mode1.envMode;
  316.       case 7: /* envNbSweep */
  317.     return soundReg->mode1.envNbSweep;
  318.       case 8: /* frequency */
  319.       case FREQUENCY:
  320.     return (soundReg->mode1.frequencyHigh << 8) + soundReg->mode1.frequencyLow;
  321.       case 9: /* counter_ConsSel */
  322.     return soundReg->mode1.counter_ConsSel;
  323.       case 10: /* Sound1_To_SO1 */
  324.     return soundReg->control.Sound1_To_SO1;
  325.       case 11: /* Sound1_To_SO2 */
  326.     return soundReg->control.Sound1_To_SO2;
  327.       case 12: /* Sound1_On_Off */
  328.     return soundReg->control.Sound1_On_Off;
  329.       }
  330.   } else if(mode == 2) {
  331.     switch(line)
  332.       {
  333.       case 0: /* patternDuty */
  334.     return soundReg->mode2.patternDuty;
  335.       case 1: /* soundLength */
  336.     return soundReg->mode2.soundLength;
  337.       case 2: /* envInitialValue */
  338.     return soundReg->mode2.envInitialValue;
  339.       case 3: /* envMode */
  340.     return soundReg->mode2.envMode;
  341.       case 4: /* envNbStep */
  342.     return soundReg->mode2.envNbStep;
  343.       case 5: /* frequency */
  344.       case FREQUENCY:
  345.     return (soundReg->mode2.frequencyHigh << 8) + soundReg->mode2.frequencyLow;
  346.       case 6: /* counter_ConsSel */
  347.     return soundReg->mode2.counter_ConsSel;
  348.       case 7: /* Sound2_To_SO1 */
  349.     return soundReg->control.Sound2_To_SO1;
  350.       case 8: /* Sound2_To_SO2 */
  351.     return soundReg->control.Sound2_To_SO2;
  352.       case 9: /* Sound2_On_Off */
  353.     return soundReg->control.Sound2_On_Off;
  354.       }
  355.   } else if(mode == 3) {
  356.     switch(line)
  357.       {
  358.       case 0: /* on_Off */
  359.     return soundReg->mode3.on_Off;
  360.       case 1: /* soundLength */
  361.     return soundReg->mode3.soundLength;
  362.       case 2: /* selOutputLevel */
  363.     return soundReg->mode3.selOutputLevel;
  364.       case 3: /* frequency */
  365.       case FREQUENCY:
  366.     return (soundReg->mode3.frequencyHigh << 8) + soundReg->mode3.frequencyLow;
  367.       case 4: /* counter_ConsSel */
  368.     return soundReg->mode3.counter_ConsSel;
  369.       case 5: /* Sound3_To_SO1 */
  370.     return soundReg->control.Sound3_To_SO1;
  371.       case 6: /* Sound3_To_SO2 */
  372.     return soundReg->control.Sound3_To_SO2;
  373.       case 7: /* Sound3_On_Off */
  374.     return soundReg->control.Sound3_On_Off;
  375.       }
  376.   } else if(mode == 4) {
  377.     switch(line)
  378.       {
  379.       case 0: /* soundLength */
  380.     return soundReg->mode4.soundLength;
  381.       case 1: /* envInitialValue */
  382.     return soundReg->mode4.envInitialValue;
  383.       case 2: /* envMode */
  384.     return soundReg->mode4.envMode;
  385.       case 3: /* envNbStep */
  386.     return soundReg->mode4.envNbStep;
  387.       case 4: /* polyCounterFreq */
  388.     return soundReg->mode4.polyCounterFreq;
  389.       case 5: /* polyCounterStep */
  390.     return soundReg->mode4.polyCounterStep;
  391.       case 6: /* polyCounterDiv */
  392.     return soundReg->mode4.polyCounterDiv;
  393.       case 7: /* counter_ConsSel */
  394.     return soundReg->mode4.counter_ConsSel;
  395.       case 8: /* Sound4_To_SO1 */
  396.     return soundReg->control.Sound4_To_SO1;
  397.       case 9: /* Sound4_To_SO2 */
  398.     return soundReg->control.Sound4_To_SO2;
  399.       case 10: /* Sound4_On_Off */
  400.     return soundReg->control.Sound4_On_Off;
  401.       }
  402.   }
  403.   return 0;
  404. }
  405.  
  406. void update_value(int mode, int line, int value)
  407. {
  408.   if(mode == 0) {
  409.     switch(line)
  410.       {
  411.       case 0: /* global_On_Off */
  412.     soundReg->control.global_On_Off = value;
  413.     _reg_0x26 = ((char *)soundReg)[0x16];
  414.     break;
  415.       case 1: /* Vin_SO1 */
  416.     soundReg->control.Vin_SO1 = value;
  417.     _reg_0x24 = ((char *)soundReg)[0x14];
  418.     break;
  419.       case 2: /* Vin_SO2 */
  420.     soundReg->control.Vin_SO2 = value;
  421.     _reg_0x24 = ((char *)soundReg)[0x14];
  422.     break;
  423.       case 3: /* SO1_OutputLevel */
  424.     soundReg->control.SO1_OutputLevel = value;
  425.     _reg_0x24 = ((char *)soundReg)[0x14];
  426.     break;
  427.       case 4: /* SO2_OutputLevel */
  428.     soundReg->control.SO2_OutputLevel = value;
  429.     _reg_0x24 = ((char *)soundReg)[0x14];
  430.     break;
  431.       case FREQUENCY:
  432.     update_value(1, FREQUENCY, value);
  433.     update_value(2, FREQUENCY, value);
  434.     update_value(3, FREQUENCY, value);
  435.     break;
  436.       case PLAY: /* restart */
  437.     update_value(1, FREQUENCY, current_value(1, FREQUENCY));
  438.     update_value(2, FREQUENCY, current_value(2, FREQUENCY));
  439.     update_value(3, FREQUENCY, current_value(3, FREQUENCY));
  440.     soundReg->mode1.restart = value;
  441.     soundReg->mode2.restart = value;
  442.     soundReg->mode3.restart = value;
  443.     soundReg->mode4.restart = value;
  444.     _reg_0x14 = ((char *)soundReg)[0x04];
  445.     _reg_0x19 = ((char *)soundReg)[0x09];
  446.     _reg_0x1E = ((char *)soundReg)[0x0E];
  447.     _reg_0x23 = ((char *)soundReg)[0x13];
  448.     soundReg->mode1.restart = 0;
  449.     soundReg->mode2.restart = 0;
  450.     soundReg->mode3.restart = 0;
  451.     soundReg->mode4.restart = 0;
  452.     break;
  453.       }
  454.   } else if(mode == 1) {
  455.     switch(line)
  456.       {
  457.       case 0: /* sweepTime */
  458.     soundReg->mode1.sweepTime = value;
  459.     _reg_0x10 = ((char *)soundReg)[0x00];
  460.     break;
  461.       case 1: /* sweepMode */
  462.     soundReg->mode1.sweepMode = value;
  463.     _reg_0x10 = ((char *)soundReg)[0x00];
  464.     break;
  465.       case 2: /* sweepShifts */
  466.     soundReg->mode1.sweepShifts = value;
  467.     _reg_0x10 = ((char *)soundReg)[0x00];
  468.     break;
  469.       case 3: /* patternDuty */
  470.     soundReg->mode1.patternDuty = value;
  471.     _reg_0x11 = ((char *)soundReg)[0x01];
  472.     break;
  473.       case 4: /* soundLength */
  474.     soundReg->mode1.soundLength = value;
  475.     _reg_0x11 = ((char *)soundReg)[0x01];
  476.     break;
  477.       case 5: /* envInitialValue */
  478.     soundReg->mode1.envInitialValue = value;
  479.     _reg_0x12 = ((char *)soundReg)[0x02];
  480.     break;
  481.       case 6: /* envMode */
  482.     soundReg->mode1.envMode = value;
  483.     _reg_0x12 = ((char *)soundReg)[0x02];
  484.     break;
  485.       case 7: /* envNbSweep */
  486.     soundReg->mode1.envNbSweep = value;
  487.     _reg_0x12 = ((char *)soundReg)[0x02];
  488.     break;
  489.       case 8: /* frequency */
  490.       case FREQUENCY:
  491.     soundReg->mode1.frequencyHigh = value >> 8;
  492.     soundReg->mode1.frequencyLow  = value;
  493.     _reg_0x13 = ((char *)soundReg)[0x03];
  494.     _reg_0x14 = ((char *)soundReg)[0x04];
  495.     break;
  496.       case 9: /* counter_ConsSel */
  497.     soundReg->mode1.counter_ConsSel = value;
  498.     _reg_0x14 = ((char *)soundReg)[0x04];
  499.     break;
  500.       case 10: /* Sound1_To_SO1 */
  501.     soundReg->control.Sound1_To_SO1 = value;
  502.     _reg_0x25 = ((char *)soundReg)[0x15];
  503.     break;
  504.       case 11: /* Sound1_To_SO2 */
  505.     soundReg->control.Sound1_To_SO2 = value;
  506.     _reg_0x25 = ((char *)soundReg)[0x15];
  507.     break;
  508.       case 12: /* Sound1_On_Off */
  509.     soundReg->control.Sound1_On_Off = value;
  510.     _reg_0x26 = ((char *)soundReg)[0x16];
  511.     break;
  512.       case PLAY: /* restart */
  513.     update_value(mode, FREQUENCY, current_value(mode, FREQUENCY));
  514.     soundReg->mode1.restart = value;
  515.     _reg_0x14 = ((char *)soundReg)[0x04];
  516.     soundReg->mode1.restart = 0;
  517.     break;
  518.       }
  519.   } else if(mode == 2) {
  520.     switch(line)
  521.       {
  522.       case 0: /* patternDuty */
  523.     soundReg->mode2.patternDuty = value;
  524.     _reg_0x16 = ((char *)soundReg)[0x06];
  525.     break;
  526.       case 1: /* soundLength */
  527.     soundReg->mode2.soundLength = value;
  528.     _reg_0x16 = ((char *)soundReg)[0x06];
  529.     break;
  530.       case 2: /* envInitialValue */
  531.     soundReg->mode2.envInitialValue = value;
  532.     _reg_0x17 = ((char *)soundReg)[0x07];
  533.     break;
  534.       case 3: /* envMode */
  535.     soundReg->mode2.envMode = value;
  536.     _reg_0x17 = ((char *)soundReg)[0x07];
  537.     break;
  538.       case 4: /* envNbStep */
  539.     soundReg->mode2.envNbStep = value;
  540.     _reg_0x17 = ((char *)soundReg)[0x07];
  541.     break;
  542.       case 5: /* frequency */
  543.       case FREQUENCY:
  544.     soundReg->mode2.frequencyHigh = value >> 8;
  545.     soundReg->mode2.frequencyLow  = value;
  546.     _reg_0x18 = ((char *)soundReg)[0x08];
  547.     _reg_0x19 = ((char *)soundReg)[0x09];
  548.     break;
  549.       case 6: /* counter_ConsSel */
  550.     soundReg->mode2.counter_ConsSel = value;
  551.     _reg_0x19 = ((char *)soundReg)[0x09];
  552.     break;
  553.       case 7: /* Sound2_To_SO1 */
  554.     soundReg->control.Sound2_To_SO1 = value;
  555.     _reg_0x25 = ((char *)soundReg)[0x15];
  556.     break;
  557.       case 8: /* Sound2_To_SO2 */
  558.     soundReg->control.Sound2_To_SO2 = value;
  559.     _reg_0x25 = ((char *)soundReg)[0x15];
  560.     break;
  561.       case 9: /* Sound2_On_Off */
  562.     soundReg->control.Sound2_On_Off = value;
  563.     _reg_0x26 = ((char *)soundReg)[0x16];
  564.     break;
  565.       case PLAY: /* restart */
  566.     update_value(mode, FREQUENCY, current_value(mode, FREQUENCY));
  567.     soundReg->mode2.restart = value;
  568.     _reg_0x19 = ((char *)soundReg)[0x09];
  569.     soundReg->mode2.restart = 0;
  570.     break;
  571.       }
  572.   } else if(mode == 3) {
  573.     switch(line)
  574.       {
  575.       case 0: /* on_Off */
  576.     soundReg->mode3.on_Off = value;
  577.     _reg_0x1A = ((char *)soundReg)[0x0A];
  578.     break;
  579.       case 1: /* soundLength */
  580.     soundReg->mode3.soundLength = value;
  581.     _reg_0x1B = ((char *)soundReg)[0x0B];
  582.     break;
  583.       case 2: /* selOutputLevel */
  584.     soundReg->mode3.selOutputLevel = value;
  585.     _reg_0x1C = ((char *)soundReg)[0x0C];
  586.     break;
  587.       case 3: /* frequency */
  588.       case FREQUENCY:
  589.     soundReg->mode3.frequencyHigh = value >> 8;
  590.     soundReg->mode3.frequencyLow  = value;
  591.     _reg_0x1D = ((char *)soundReg)[0x0D];
  592.     _reg_0x1E = ((char *)soundReg)[0x0E];
  593.     break;
  594.       case 4: /* counter_ConsSel */
  595.     soundReg->mode3.counter_ConsSel = value;
  596.     _reg_0x1E = ((char *)soundReg)[0x0E];
  597.     break;
  598.       case 5: /* Sound3_To_SO1 */
  599.     soundReg->control.Sound3_To_SO1 = value;
  600.     _reg_0x25 = ((char *)soundReg)[0x15];
  601.     break;
  602.       case 6: /* Sound3_To_SO2 */
  603.     soundReg->control.Sound3_To_SO2 = value;
  604.     _reg_0x25 = ((char *)soundReg)[0x15];
  605.     break;
  606.       case 7: /* Sound3_On_Off */
  607.     soundReg->control.Sound3_On_Off = value;
  608.     _reg_0x26 = ((char *)soundReg)[0x16];
  609.     break;
  610.       case PLAY: /* restart */
  611.     update_value(mode, FREQUENCY, current_value(mode, FREQUENCY));
  612.     soundReg->mode3.restart = value;
  613.     _reg_0x1E = ((char *)soundReg)[0x0E];
  614.     soundReg->mode3.restart = 0;
  615.     break;
  616.       }
  617.   } else if(mode == 4) {
  618.     switch(line)
  619.       {
  620.       case 0: /* soundLength */
  621.     soundReg->mode4.soundLength = value;
  622.     _reg_0x20 = ((char *)soundReg)[0x10];
  623.     break;
  624.       case 1: /* envInitialValue */
  625.     soundReg->mode4.envInitialValue = value;
  626.     _reg_0x21 = ((char *)soundReg)[0x11];
  627.     break;
  628.       case 2: /* envMode */
  629.     soundReg->mode4.envMode = value;
  630.     _reg_0x21 = ((char *)soundReg)[0x11];
  631.     break;
  632.       case 3: /* envNbStep */
  633.     soundReg->mode4.envNbStep = value;
  634.     _reg_0x21 = ((char *)soundReg)[0x11];
  635.     break;
  636.       case 4: /* polyCounterFreq */
  637.     soundReg->mode4.polyCounterFreq = value;
  638.     _reg_0x22 = ((char *)soundReg)[0x12];
  639.     break;
  640.       case 5: /* polyCounterStep */
  641.     soundReg->mode4.polyCounterStep = value;
  642.     _reg_0x22 = ((char *)soundReg)[0x12];
  643.     break;
  644.       case 6: /* polyCounterDiv */
  645.     soundReg->mode4.polyCounterDiv = value;
  646.     _reg_0x22 = ((char *)soundReg)[0x12];
  647.     break;
  648.       case 7: /* counter_ConsSel */
  649.     soundReg->mode4.counter_ConsSel = value;
  650.     _reg_0x23 = ((char *)soundReg)[0x13];
  651.     break;
  652.       case 8: /* Sound4_To_SO1 */
  653.     soundReg->control.Sound4_To_SO1 = value;
  654.     _reg_0x25 = ((char *)soundReg)[0x15];
  655.     break;
  656.       case 9: /* Sound4_To_SO2 */
  657.     soundReg->control.Sound4_To_SO2 = value;
  658.     _reg_0x25 = ((char *)soundReg)[0x15];
  659.     break;
  660.       case 10: /* Sound4_On_Off */
  661.     soundReg->control.Sound4_On_Off = value;
  662.     _reg_0x26 = ((char *)soundReg)[0x16];
  663.     break;
  664.       case PLAY: /* restart */
  665.     soundReg->mode4.restart = value;
  666.     _reg_0x23 = ((char *)soundReg)[0x13];
  667.     soundReg->mode4.restart = 0;
  668.     break;
  669.       }
  670.   }
  671. }
  672.  
  673. void cls()
  674. {
  675.   int x, y;
  676.  
  677.   for(y = 0; y < 18; y++)
  678.     for(x = 0; x < 20; x++) {
  679.       gotoxy(x, y);
  680.       setchar(' ');
  681.     }
  682. }
  683.  
  684. int draw_screen(int mode)
  685. {
  686.   int i;
  687.  
  688.   cls();
  689.   gotoxy(FIRST_X, TITLE_Y);
  690.   print(params[0].name);
  691.  
  692.   for(i = 0; params[i+1].name; i++) {
  693.     gotoxy(FIRST_X, FIRST_Y+i);
  694.     print(params[i+1].name);
  695.     gotoxy(VAL_X, FIRST_Y+i);
  696.     printn(current_value(mode, i), 10);
  697.   }
  698.   return i-1;
  699. }
  700.  
  701.  
  702. void play_music(int mode)
  703. {
  704.   int i = 0;
  705.  
  706.   while(music[i] != END) {
  707.     if(music[i] != SILENCE) {
  708.       update_value(mode, FREQUENCY, frequencies[music[i]]);
  709.       update_value(mode, PLAY, 1);
  710.     }
  711.     delay(20000);
  712.     i++;
  713.   }
  714. }
  715.  
  716. void dump_registers()
  717. {
  718.   unsigned char reg;
  719.   int i, j;
  720.  
  721.   cls();
  722.   gotoxy(FIRST_X, TITLE_Y);
  723.   print("Register Dump");
  724.  
  725.   for(i = 0, j = 0; i <= 0x16; i++, j++) {
  726.     if(i == 0x05 || i == 0x0F)
  727.       i++;
  728.     if(j%2 == 0) {
  729.       gotoxy(FIRST_X, FIRST_Y+j/2);
  730.       print("0xFF");
  731.     } else {
  732.       gotoxy(FIRST_X+6, FIRST_Y+j/2);
  733.       putchar('-');
  734.     }
  735.     printn(i+0x10, 16);
  736.     if(j%2 == 0) {
  737.       gotoxy(VAL_X, FIRST_Y+j/2);
  738.     } else {
  739.       gotoxy(VAL_X+2, FIRST_Y+j/2);
  740.       putchar('-');
  741.     }
  742.     reg = ((char *)soundReg)[i];
  743.     if(reg < 0x10) putchar('0');
  744.     printn(reg, 16);
  745.   }
  746. }
  747.  
  748. void wait_event(int mode)
  749. {
  750.   int input, i, y, last_y;
  751.  
  752.   while(1) {
  753.     params = params_array[mode];
  754.     last_y = draw_screen(mode) + FIRST_Y;
  755.     y = FIRST_Y;
  756.     gotoxy(ARROW_X, y);
  757.     setchar(ARROW_CHAR);
  758.  
  759.     while(1) {
  760.       input = joypad();
  761.       if(input & J_UP) {
  762.     gotoxy(ARROW_X, y); setchar(SPACE_CHAR);
  763.     if(--y < FIRST_Y)
  764.       y = last_y;
  765.     gotoxy(ARROW_X, y); setchar(ARROW_CHAR);
  766.       } else if (input & J_DOWN) {
  767.     gotoxy(ARROW_X, y); setchar(SPACE_CHAR);
  768.     if(++y > last_y)
  769.       y = FIRST_Y;
  770.     gotoxy(ARROW_X, y); setchar(ARROW_CHAR);
  771.       } else if (input & J_LEFT) {
  772.     i = current_value(mode, y-FIRST_Y);
  773.     if(i > 0) {
  774.       if(input & J_A)
  775.         i = MAX(i-10, 0);
  776.       else if(input & J_B)
  777.         i = 0;
  778.       else
  779.         i--;
  780.       update_value(mode, y-FIRST_Y, i);
  781.       gotoxy(VAL_X, y); print("    ");
  782.       gotoxy(VAL_X, y); printn(i, 10);
  783.     }
  784.       } else if (input & J_RIGHT) {
  785.     i = current_value(mode, y-FIRST_Y);
  786.     if(i < params[y-FIRST_Y+1].max) {
  787.       if(input & J_A)
  788.         i = MIN(i+10, params[y-FIRST_Y+1].max);
  789.       else if(input & J_B)
  790.         i = params[y-FIRST_Y+1].max;
  791.       else
  792.         i++;
  793.       update_value(mode, y-FIRST_Y, i);
  794.       gotoxy(VAL_X, y); print("    ");
  795.       gotoxy(VAL_X, y); printn(i, 10);
  796.     }
  797.       } else if (input & J_START) {
  798.     if(input & J_A)
  799.       play_music(mode);
  800.     else
  801.       update_value(mode, PLAY, 1);
  802.     waitpadup();
  803.       } else if (input & J_SELECT) {
  804.     if(input & J_A)
  805.       dump_registers();
  806.     else
  807.       mode = (mode+1) % NB_MODES;
  808.     waitpadup();
  809.     break;
  810.       }
  811.       for(i = 0; i < 200 && input == joypad(); i++)
  812.     delay(50);
  813.     }
  814.   }
  815. }
  816.  
  817. void main()
  818. {
  819.   struct SoundReg s = {
  820.     { 0, 0, 0, 0,
  821.       1, 2,
  822.       3, 0, 4,
  823.       0x73,
  824.       6, 0, 0, 0 },
  825.     { 0,
  826.       1, 2,
  827.       4, 0, 8,
  828.       0xD7,
  829.       6, 0, 0, 0 },
  830.     { 0, 1,
  831.       0,
  832.       0, 1, 0,
  833.       0xD6,
  834.       6, 0, 0, 0 },
  835.     { 0,
  836.       58, 0,
  837.       1, 0, 10,
  838.       0, 0, 0,
  839.       0, 1, 0 },
  840.     { 7, 0, 7, 0,
  841.       1, 1, 1, 1, 1, 1, 1, 1,
  842.       0, 0, 0, 0, 0, 1 }
  843.   };
  844.  
  845.   soundReg = &s;
  846.   _reg_0x10 = ((char *)soundReg)[0x00];
  847.   _reg_0x11 = ((char *)soundReg)[0x01];
  848.   _reg_0x12 = ((char *)soundReg)[0x02];
  849.   _reg_0x13 = ((char *)soundReg)[0x03];
  850.   _reg_0x14 = ((char *)soundReg)[0x04];
  851.  
  852.   _reg_0x16 = ((char *)soundReg)[0x06];
  853.   _reg_0x17 = ((char *)soundReg)[0x07];
  854.   _reg_0x18 = ((char *)soundReg)[0x08];
  855.   _reg_0x19 = ((char *)soundReg)[0x09];
  856.   _reg_0x1A = ((char *)soundReg)[0x0A];
  857.   _reg_0x1B = ((char *)soundReg)[0x0B];
  858.   _reg_0x1C = ((char *)soundReg)[0x0C];
  859.   _reg_0x1D = ((char *)soundReg)[0x0D];
  860.   _reg_0x1E = ((char *)soundReg)[0x0E];
  861.  
  862.   _reg_0x20 = ((char *)soundReg)[0x10];
  863.   _reg_0x21 = ((char *)soundReg)[0x11];
  864.   _reg_0x22 = ((char *)soundReg)[0x12];
  865.   _reg_0x23 = ((char *)soundReg)[0x13];
  866.   _reg_0x24 = ((char *)soundReg)[0x14];
  867.   _reg_0x25 = ((char *)soundReg)[0x15];
  868.   _reg_0x26 = ((char *)soundReg)[0x16];
  869.  
  870.   cls();
  871.  
  872.   wait_event(1);
  873. }
  874.